#include "StdAfx.h"
#include "SelfModifeCode.h"
#include <Windows.h>
#include <stdio.h>
#include "lclog.h"
#pragma  pack(1)
typedef struct TAGFunRec
{
	int dwNameIndex;
	char szFunName[100];
	char * pfun;
}FunRec;
typedef struct TAGFunjumper
{
	unsigned char pushad;//0x60
	unsigned char push;//0x68
	int pushdata;
	unsigned char call;
	int calldata;
	unsigned char popad;//0x61
	unsigned char jump;
	int jmpdata;
	int nop;
}Funjumper;
#pragma  pack()
GUID g_guid = {
	0x1D6F7D1E,
	0x0EACD,
	0x11CD,
	{0x95, 0x70, 0x0, 0xAA, 0x0, 0x51, 0x0E5, 0x0D4}
};
IMAGE_EXPORT_DIRECTORY g_newEXPORT = {1,1,1,1,1,1,1,1,1,10,20};
char * g_pdatafunname[0x1000]={(char *)1,(char *)1,(char *)1,(char *)1,(char *)1,(char *)1,(char *)1,(char *)1,(char *)1,(char *)1,(char *)1,(char *)1,(char *)1,(char *)1,(char *)1,(char *)1,(char *)1,(char *)1,(char *)1,(char *)1,(char *)1,(char *)1,(char *)1,};
unsigned short int g_datafunOder[0x1000]={1,1,1,1,1,1,1,1,1};
unsigned int  g_datafunaddress[0x1000]={1,1,1,1,1,1,1,1,1};
char g_szfunname[0x5000]={(char)1,(char )1,(char )1,(char)1,(char )1,(char )1,(char )1,(char )1,(char )1,(char )1,(char )1,(char )1};
IMAGE_IMPORT_DESCRIPTOR g_import={1,1,1};
#pragma data_seg("text")
Funjumper g_funjumper[0x1000] = {{0xe8,0,0xe9,0},{0xe8,0,0xe9,0},{0xe8,0,0xe9,0},{0xe8,0,0xe9,0},{0xe8,0,0xe9,0},{0xe8,0,0xe9,0},{0xe8,0,0xe9,0},{0xe8,0,0xe9,0}};
#pragma data_seg()
int getFun(char *filename,int nindex,FunRec*pdata);
int GetFunIndex(unsigned char * pfile ,int nindex,FunRec*pdata);
DWORD RavtoMem(unsigned char * pfile ,DWORD rva);
DWORD MemtoRav(unsigned char * pfile ,DWORD rva);
int getEXPORT(unsigned char * file,IMAGE_EXPORT_DIRECTORY*pdata);
void hookjump();
int WriteFilePos(char * filename,DWORD npos,char * pBuffer,int nsize);
FARPROC __stdcall messagebox(DWORD dwindex);
int initdll(unsigned char * pmz)
{
	IMAGE_DOS_HEADER * hdos= (IMAGE_DOS_HEADER *)pmz;
	IMAGE_NT_HEADERS * hnt= (IMAGE_NT_HEADERS *)(pmz+hdos->e_lfanew);
	IMAGE_EXPORT_DIRECTORY *hEXPORT = (IMAGE_EXPORT_DIRECTORY *)(pmz+hnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
	if(hEXPORT ==&g_newEXPORT)
	{
		char szCurdir[512] = {0};
		GetCurrentDirectoryA(512,szCurdir);
		initLogPath(szCurdir,"mylog.log");

		HMODULE msvbvm60 =LoadLibraryA("msvbvm60_bak.dll");
		DWORD oldProtect;
		DWORD newProtect;
		VirtualProtect(g_funjumper,sizeof(g_funjumper),PAGE_EXECUTE_READWRITE,&oldProtect);
		for (int i=0;i<g_newEXPORT.NumberOfFunctions;i++)
		{
			DWORD fun = (DWORD)GetProcAddress(msvbvm60,(LPCSTR)i+g_newEXPORT.Base);
			if (g_datafunaddress[i] && (i+g_newEXPORT.Base)!=0x400)
			{
				((Funjumper*)(g_datafunaddress[i]+pmz))->jmpdata = fun-(DWORD)(&((Funjumper*)(g_datafunaddress[i]+pmz))->jmpdata) - 4;
			}
		}
		VirtualProtect(g_funjumper,sizeof(g_funjumper),oldProtect,&newProtect);
		return 0;
	}
	char szselfname[512] = {0};
	char sznewname[512] = {0};
	char szCurdir[512] = {0};
	GetModuleFileNameA((HMODULE)pmz,szselfname,512);
	GetCurrentDirectoryA(512,szCurdir);
	sprintf(sznewname,"%s\\msvbvm60.dll",szCurdir);
	::DeleteFileA(sznewname);
	CopyFileA(szselfname,sznewname,TRUE);
	unsigned char * msvbvm60 =(unsigned char *)LoadLibraryA("msvbvm60_bak.dll");
//	hookjump();
	FARPROC fun = GetProcAddress((HMODULE)msvbvm60,(LPCSTR)0x64);
//	g_newEXPORT.TimeDateStamp = hEXPORT->TimeDateStamp; 
	g_newEXPORT = *hEXPORT;
	FunRec data;
	getEXPORT(msvbvm60,&g_newEXPORT);
	g_newEXPORT.AddressOfFunctions = (DWORD)&g_datafunaddress[0]-(DWORD)pmz;
	g_newEXPORT.AddressOfNames =(DWORD) &g_pdatafunname[0]-(DWORD)pmz;
	g_newEXPORT.AddressOfNameOrdinals = (DWORD)&g_datafunOder[0]-(DWORD)pmz;	
	memset(g_datafunOder,0,sizeof(g_datafunOder));
	memset(g_datafunOder,0,sizeof(g_pdatafunname));
	memset(g_datafunOder,0,sizeof(g_datafunaddress));
	char daatddd[100]; 
	DWORD curfunname = 0;
	int nfunname=0;
	DWORD cmpdata = 0;
		for (int i =0;i<g_newEXPORT.NumberOfFunctions;i++)
		{
			memset(&data,0,sizeof(FunRec));
			GetFunIndex(msvbvm60,i,&data);
			sprintf(daatddd,"%x\n",i);
//			::OutputDebugStringA(daatddd);

			if (data.dwNameIndex>=0)
			{
				::OutputDebugStringA(data.szFunName);
				strcpy(&g_szfunname[curfunname],data.szFunName);
				g_pdatafunname[data.dwNameIndex] = &g_szfunname[curfunname]-(DWORD)pmz;
				g_datafunOder[data.dwNameIndex] = i;
//				nfunname++;
				curfunname+=(strlen(data.szFunName)+1);
			}
			else
			{

			}
			if (data.pfun)
			{
				g_datafunaddress[i] = (DWORD)&g_funjumper[i]-(DWORD)pmz;
				g_funjumper[i].jump=0xe9;
				//g_funjumper[i].push = 0x68;
				//g_funjumper[i].call=0xe8;
				//g_funjumper[i].pushdata = i+g_newEXPORT.Base;
				//			g_funjumper[i].calldata = (int)messagebox - (int)&g_funjumper[i].jump;
				//				g_funjumper[i].jmpdata = 0xe0;
				g_funjumper[i].push = 0x90;
				g_funjumper[i].call=0x90;
				g_funjumper[i].calldata = 0x90909090;
				g_funjumper[i].pushdata = 0x90909090;
				g_funjumper[i].pushad = 0x60;
				g_funjumper[i].popad = 0x61;
				DWORD fun = (DWORD)GetProcAddress((HMODULE)msvbvm60,(LPCSTR)i+g_newEXPORT.Base);
				g_funjumper[i].jmpdata = fun-(DWORD)(&g_funjumper[i].jmpdata) - 4;
				if ((i+g_newEXPORT.Base)==0x400)
				{
					memcpy(&g_funjumper[i],&g_guid,sizeof(g_guid));
				}
			}
			else
			{
				g_datafunaddress[i] = 0;
			}
//			g_datafunaddress[i] = (DWORD)hookjump-(DWORD)pmz;
//			g_datafunaddress[i] = (DWORD)data.pfun;
			//if (!cmpdata)
			//{
			//	cmpdata = g_datafunaddress[0];
			//}
			//if (g_datafunaddress[0]!=cmpdata)
			//{
			//	printf("%x %x %x\n",i,g_datafunaddress[i],g_datafunaddress[0]);
			//}
			printf("%x %x\n",i,g_datafunaddress[i]);
		}
		DWORD oldProtect;
		DWORD newProtect;
		VirtualProtect(&hnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT],8,PAGE_EXECUTE_READWRITE,&oldProtect);
		hnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = (DWORD)&g_newEXPORT-(DWORD)pmz;
		hnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = (DWORD)&g_szfunname[0x5000]+1 - (DWORD)&g_newEXPORT;
		VirtualProtect(&hnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT],8,oldProtect,&newProtect);
		DWORD dwRva = (DWORD)&hnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] -(DWORD)pmz;
		WriteFilePos("msvbvm60.dll",(DWORD)&hnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]-(DWORD)pmz,
			(char *)&hnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT],
			sizeof(hnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]));
		WriteFilePos("msvbvm60.dll",MemtoRav(pmz ,(DWORD)&g_newEXPORT),(char *)&g_newEXPORT,sizeof(g_newEXPORT));
		WriteFilePos("msvbvm60.dll",MemtoRav(pmz ,(DWORD)&g_pdatafunname[0]),(char *)&g_pdatafunname[0],sizeof(g_pdatafunname));
		WriteFilePos("msvbvm60.dll",MemtoRav(pmz ,(DWORD)&g_datafunOder[0]),(char *)&g_datafunOder[0],sizeof(g_datafunOder));
		WriteFilePos("msvbvm60.dll",MemtoRav(pmz ,(DWORD)&g_szfunname[0]),(char *)&g_szfunname[0],sizeof(g_szfunname));
		WriteFilePos("msvbvm60.dll",MemtoRav(pmz ,(DWORD)&g_datafunaddress[0]),(char *)&g_datafunaddress[0],sizeof(g_datafunaddress));
		WriteFilePos("msvbvm60.dll",MemtoRav(pmz ,(DWORD)&g_funjumper[0]),(char *)&g_funjumper[0],sizeof(g_funjumper));
		VirtualProtect(&g_funjumper[0],sizeof(g_funjumper),PAGE_EXECUTE_READWRITE,&oldProtect);
//		IMAGE_EXPORT_DIRECTORY *hEXPORT = (IMAGE_EXPORT_DIRECTORY *)(pmz+hnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
//	g_szfunname
//	g_newEXPORT->
//	char * * pdatafunname = (char * *)(((unsigned int)pmz) + hEXPORT->AddressOfNames);
//	unsigned short int * pdatafunOder = (unsigned short int *)(((unsigned int)pmz) + hEXPORT->AddressOfNameOrdinals);
//	unsigned int * pdatafunaddress = (unsigned int *)(((unsigned int)pmz) + hEXPORT->AddressOfFunctions);
	return 0;
}
FARPROC __stdcall messagebox(DWORD dwindex)
{
//	char sznewname[512] = {0};
	DWORD * pret = (DWORD *)&dwindex;
	pret++;
//	sprintf(sznewname,"%08x",*pret);
//	::MessageBoxA(NULL,sznewname,sznewname,MB_OK);
	mylog("%x %x\n",*pret,dwindex);
	return GetProcAddress(LoadLibraryA("msvbvm60_bak.dll"),(LPCSTR)dwindex);
}
void __declspec(naked) hookjump()
{
	__asm
	{
		push 0x64
		call messagebox;
		jmp eax
	}
}
int getEXPORT(unsigned char * file,IMAGE_EXPORT_DIRECTORY*pdata)
{
	IMAGE_DOS_HEADER * hdos= (IMAGE_DOS_HEADER *)file;
	IMAGE_NT_HEADERS * hnt= (IMAGE_NT_HEADERS *)(file+hdos->e_lfanew);
	IMAGE_SECTION_HEADER * hSECTION =(IMAGE_SECTION_HEADER *)(file+hdos->e_lfanew+sizeof(IMAGE_NT_HEADERS));
	DWORD dwRav;
	//for (int i =0;i<hnt->FileHeader.NumberOfSections;i++)
	//{
	//	if (hSECTION[i].VirtualAddress<hnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
	//		&&(hnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress+
	//		hnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)<
	//		(hSECTION[i].VirtualAddress+hSECTION[i].Misc.VirtualSize))
	//	{
	//		dwRav =hSECTION[i].PointerToRawData-hSECTION[i].VirtualAddress;
	//		break;
	//	}
	//	
	//}
	//	hSECTION->
	IMAGE_EXPORT_DIRECTORY *hEXPORT = (IMAGE_EXPORT_DIRECTORY *)RavtoMem(file,hnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
	*pdata = *hEXPORT;
	return 0;
}
int getFun(char *filename,int nindex,FunRec*pdata)
{
	unsigned char  *pBuf;
	int i;
	HANDLE hMapFile; 
	HANDLE hFile = CreateFileA(filename,               // file to open
		GENERIC_READ|GENERIC_WRITE,          // open for reading
		FILE_SHARE_READ,       // share for reading
		NULL,                  // default security
		OPEN_EXISTING,         // existing file only
		FILE_ATTRIBUTE_NORMAL, // normal file
		NULL);                 // no attr. template
	if (hFile && INVALID_HANDLE_VALUE!=hFile)
	{
		DWORD filesize;
		filesize =GetFileSize(hFile,&filesize);

		hMapFile = CreateFileMapping(
			hFile,    // use paging file
			NULL,                    // default security 
			PAGE_READWRITE,          // read/write access
			0,                       // max. object size 
			filesize,                // buffer size  
			//			((filesize.LowPart/0x1000)+1)*0x1000,                // buffer size  
			NULL);
		pBuf = (unsigned char *) MapViewOfFile(hMapFile,   // handle to map object
			FILE_MAP_ALL_ACCESS, // read/write permission
			0,                   
			0,                   
			filesize);
		GetFunIndex(pBuf,nindex,pdata);
		CloseHandle(hMapFile);
		CloseHandle(hFile);
	}
	else
	{
		return -1;
	}
	return 0;
}
int GetFunIndex(unsigned char * pfile ,int nindex,FunRec*pdata)
{
	IMAGE_DOS_HEADER * hdos= (IMAGE_DOS_HEADER *)pfile;
	IMAGE_NT_HEADERS * hnt= (IMAGE_NT_HEADERS *)(pfile+hdos->e_lfanew);
	IMAGE_SECTION_HEADER * hSECTION =(IMAGE_SECTION_HEADER *)(pfile+hdos->e_lfanew+sizeof(IMAGE_NT_HEADERS));
	DWORD dwRav;
	//for (int i =0;i<hnt->FileHeader.NumberOfSections;i++)
	//{
	//	if (hSECTION[i].VirtualAddress<hnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
	//		&&(hnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress+
	//		hnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)<
	//		(hSECTION[i].VirtualAddress+hSECTION[i].Misc.VirtualSize))
	//	{
	//		dwRav =hSECTION[i].PointerToRawData-hSECTION[i].VirtualAddress;
	//		break;
	//	}
	//	
	//}
	//	hSECTION->
	IMAGE_EXPORT_DIRECTORY *hEXPORT = (IMAGE_EXPORT_DIRECTORY *)RavtoMem(pfile,hnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
	DWORD * pdatafunname = (DWORD *)RavtoMem(pfile,hEXPORT->AddressOfNames);
	unsigned short int * pdatafunOder = (unsigned short int *)RavtoMem(pfile,hEXPORT->AddressOfNameOrdinals);
	unsigned int * pdatafunaddress = (unsigned int *)RavtoMem(pfile,hEXPORT->AddressOfFunctions);
	//char * * pdatafunname = (char * *)(((unsigned int)pfile) + hEXPORT->AddressOfNames);
	//unsigned short int * pdatafunOder = (unsigned short int *)(((unsigned int)pfile) + hEXPORT->AddressOfNameOrdinals);
	//unsigned int * pdatafunaddress = (unsigned int *)(((unsigned int)pfile) + hEXPORT->AddressOfFunctions);
	int nfunname = -1;
	for (int i =0;i<hEXPORT->NumberOfNames;i++)
	{
		if (pdatafunOder[i] == nindex)
		{
			nfunname = i;
			break;
		}
	}
	if (nfunname>=0)
	{
		char * pfunname = (char *)((unsigned int)pfile)+pdatafunname[nfunname];
		strcpy(pdata->szFunName,pfunname);
	}
	pdata->dwNameIndex = nfunname;
	if (pdatafunaddress[nindex])
	{
		char * pfun = (char *)((unsigned int)pfile)+pdatafunaddress[nindex];
		pdata->pfun = pfun;
	}
	else
	{
		pdata->pfun = 0;
	}
	return 0;
}
DWORD RavtoMem(unsigned char * pfile ,DWORD rva)
{
	IMAGE_DOS_HEADER * hdos= (IMAGE_DOS_HEADER *)pfile;
	IMAGE_NT_HEADERS * hnt= (IMAGE_NT_HEADERS *)(pfile+hdos->e_lfanew);
	IMAGE_SECTION_HEADER * hSECTION =(IMAGE_SECTION_HEADER *)(pfile+hdos->e_lfanew+sizeof(IMAGE_NT_HEADERS));
	DWORD dwRva;
	//for (int i =0;i<hnt->FileHeader.NumberOfSections;i++)
	//{
	//	if (hSECTION[i].VirtualAddress<rva
	//		&&(rva<(hSECTION[i].VirtualAddress+hSECTION[i].Misc.VirtualSize)))
	//	{
	//		dwRva =hSECTION[i].PointerToRawData-hSECTION[i].VirtualAddress;
	//		break;
	//	}

	//}
//	return (DWORD)(rva+pfile+dwRva);
	return (DWORD)(rva+pfile);
}
DWORD MemtoRav(unsigned char * pfile ,DWORD rva)
{
	IMAGE_DOS_HEADER * hdos= (IMAGE_DOS_HEADER *)pfile;
	IMAGE_NT_HEADERS * hnt= (IMAGE_NT_HEADERS *)(pfile+hdos->e_lfanew);
	IMAGE_SECTION_HEADER * hSECTION =(IMAGE_SECTION_HEADER *)(pfile+hdos->e_lfanew+sizeof(IMAGE_NT_HEADERS));
	rva-=(DWORD)pfile;
	DWORD dwRva;
	for (int i =0;i<hnt->FileHeader.NumberOfSections;i++)
	{
		if (hSECTION[i].VirtualAddress<=rva
			&&(rva<(hSECTION[i].VirtualAddress+hSECTION[i].Misc.VirtualSize)))
		{
			dwRva =hSECTION[i].VirtualAddress -hSECTION[i].PointerToRawData;
			break;
		}

	}
	DWORD dwdata = (DWORD)(rva-dwRva);
	return (DWORD)(rva-dwRva);
//	return (DWORD)(rva+pfile);
}
int WriteFilePos(char * filename,DWORD npos,char * pBuffer,int nsize)
{
	FILE * pfile = fopen(filename,"rb+");
	if (pfile)
	{
		fseek(pfile,npos,0);
		fwrite(pBuffer,nsize,1,pfile);
		fclose(pfile);
	};
	return 0;
}